package org.lucava.boatskeeper.client.presenter;

import org.lucava.boatskeeper.client.BoatsKeeperServiceAsync;
import org.lucava.boatskeeper.client.event.boat.BoatUpdatedEvent;
import org.lucava.boatskeeper.client.event.boat.EditBoatCancelledEvent;
import org.lucava.boatskeeper.shared.Boat;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;

public class EditBoatPresenter implements Presenter {
	public interface Display {
		HasClickHandlers getSaveButton();

		HasClickHandlers getCancelButton();

		HasValue<String> getBoatName();

		HasValue<String> getType();

		HasValue<String> getDescription();

		HasValue<String> getLatitude();

		HasValue<String> getLongitude();

		Widget asWidget();

	}

	private Boat mBoat;
	private final BoatsKeeperServiceAsync mRpcService;
	private final HandlerManager mEventBus;
	private final Display mDisplay;

	public EditBoatPresenter(BoatsKeeperServiceAsync rpcService,
			HandlerManager eventBus, Display display) {
		this.mRpcService = rpcService;
		this.mEventBus = eventBus;
		this.mBoat = new Boat();
		this.mDisplay = display;
		bind();
	}

	public EditBoatPresenter(BoatsKeeperServiceAsync rpcService,
			HandlerManager eventBus, Display display, Integer id) {
		this.mRpcService = rpcService;
		this.mEventBus = eventBus;
		this.mDisplay = display;
		bind();

		rpcService.getBoat(id, new AsyncCallback<Boat>() {
			public void onSuccess(Boat result) {
				if (result != null) {
					mBoat = result;
					EditBoatPresenter.this.mDisplay.getBoatName().setValue(
							mBoat.getName());
					EditBoatPresenter.this.mDisplay.getType().setValue(
							mBoat.getType());
					EditBoatPresenter.this.mDisplay.getDescription().setValue(
							mBoat.getDescription());
					EditBoatPresenter.this.mDisplay.getLongitude().setValue(
							mBoat.getLongitude().toString());
					EditBoatPresenter.this.mDisplay.getLatitude().setValue(
							mBoat.getLatitude().toString());
				}
			}

			public void onFailure(Throwable caught) {
				Window.alert("Error retrieving Boat");
			}
		});

	}

	public void bind() {
		this.mDisplay.getSaveButton().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				doSave();
			}
		});

		this.mDisplay.getCancelButton().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				mEventBus.fireEvent(new EditBoatCancelledEvent());
			}
		});
	}

	public void go(final HasWidgets container) {
		container.clear();
		container.add(mDisplay.asWidget());
	}

	private void doSave() {
		mBoat.setName(mDisplay.getBoatName().getValue());
		mBoat.setType(mDisplay.getType().getValue());
		mBoat.setDescription(mDisplay.getDescription().getValue());

		float longitude = 0;
		try {
			longitude = Float.parseFloat(mDisplay.getLongitude().getValue());
		} catch (NumberFormatException nfe) {

		}

		mBoat.setLongitude(longitude);

		float latitude = 0;
		try {
			latitude = Float.parseFloat(mDisplay.getLatitude().getValue());
		} catch (NumberFormatException nfe) {

		}
		mBoat.setLatitude(latitude);

		mRpcService.updateBoat(mBoat, new AsyncCallback<Boat>() {
			public void onSuccess(Boat result) {
				mEventBus.fireEvent(new BoatUpdatedEvent(result));
			}

			public void onFailure(Throwable caught) {
				Window.alert("Error updating boat!");
			}
		});
	}

}
